# print("Hello, World!")
##面向对象编程
# class Person:
#     def __init__(self, name, age):
#         self.name = name
#         self.age = age
#     def say_hello(self):
#         print(f"Hello, my name is {self.name} and I am {self.age} years old.")

# person = Person("John", 30)
# person.say_hello()

# class Rectangle:
#     def __init__(self,width,height):
#       self.width=width
#       self.height=height
#     def get_area(self):
#       return self.width*self.height
#     def get_perimeter(self):
#       return 2*(self.width+self.height)

# rectangle=Rectangle(10,20)
# print(rectangle.get_area())
# print(rectangle.get_perimeter())

# class student:
#     count=0
#     def __init__(self,name):
#         self.name=name
#     def set_major(self,major):
#         self.major=major

# s1 = student('zhangsan')  # 创建student类的实例对象s1
# s1.set_major('math')      # 调用实例方法set_major，给s1对象添加major属性

# # dir(s1)会输出s1对象的所有属性和方法的列表，包括__init__、set_major等方法，
# # 以及通过__init__和set_major动态添加的name和major属性。
# # 例如，输出中会包含'set_major', 'name', 'major'等，说明这些是s1对象可以访问的成员。
# print(s1.name)
# print(s1.major)
# print(dir(s1))
# 第一行代码的num是什么？
# 这里的“第一行代码”如果指的是 student.num=5 这一行，
# 其实是给 student 类动态添加了一个类属性 num，并赋值为 5。
# 在此之前，student 类中并没有定义 num 属性。
# 这样做之后，student.num、s1.num、s2.num 都可以访问到这个类属性（除非实例有同名属性会遮蔽）。
# 下面是演示：

class student:
    count = 0
    def __init__(self, name):
        self.name = name
    def set_major(self, major):
        self.major = major

s1 = student('zhangsan')
s2 = student('lisi')

print(student.count)  # 输出类属性 count，结果为 0
s1.count += 1         # 这会在 s1 实例上新建一个 count实例 属性，值为 1，不影响类属性
print(s1.count)       # 输出 s1 的 count 属性，结果为 1

# print(s2.count) 为什么是0，s2为什么属于类属性
# 解释：
# s2 没有自己的 count 实例属性，所以会去类 student 上查找 count 属性
# 类属性 student.count 的初始值是 0，因此 print(s2.count) 输出 0
# 这说明：当实例没有某个属性时，会“继承”类属性（其实是通过类查找），
# 所以 s2.count 实际访问的是 student.count
# print(s2.count)       # 输出 0，因为访问的是类属性 student.count

# student.num = 5       # 动态为 student 类添加类属性 num
# print(s2.num)         # s2 没有实例属性 num，访问的是类属性，结果为 5
# print(student.num)    # 直接访问类属性 num，结果为 5

#装饰器学习
                                                                                                                                                                                                                                                                                                                                                                                                        
# 出现 NameError: name 'Person' is not defined 的原因：
# 这是因为 p=Person("张三",20) 这行代码写在了类 Person 的定义体内部。
# 在 Python 中，类体还没有完全定义完成时，类名 Person 还没有在当前作用域中可用。
# 因此在类体内部直接实例化 Person 会导致 NameError。
# 正确做法是：类定义结束后，在类体外部再创建实例对象。

class Person:
    def __init__(self, name="未知", age=18):
        self.name = name
        self.__age = age

    @property ##把类中的方法“伪装”成属性
    def age(self):
        return self.__age

    @age.setter##负责修改成员变量的值
    def age(self, new_age):
        if new_age < 1 or new_age > 120:
            print("年龄范围错误")
        else:
            self.__age = new_age

    @age.deleter##负责删除成员变量
    def age(self):
        del self.__age

# 正确的实例化方式（在类体外部）：
p = Person("张三", 20)
p.age = 123  # 这里会提示“年龄范围错误”
print(p.age) # 仍然输出20